#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<semaphore.h>
#include<vector>
using namespace std;
#define NUM 5
template<class T>
class ring 
{
  private:
    sem_t sem_blank;
    sem_t sem_data;
    vector<T> v;
    int _cap;
    int c_pos;
    int p_pos;
    void P(sem_t& t)
    {
      sem_wait(&t);
    }
    void V(sem_t& t)
    {
      sem_post(&t);
    }
  public:
    ring(int num=NUM)
      :_cap(num)
      ,c_pos(0)
      ,p_pos(0)
    {
      v.resize(_cap);
      sem_init(&sem_data,0,0);
      sem_init(&sem_blank,0,_cap);

    }
    void Push(T& in)
    {
      P(sem_blank);
      v[p_pos]=in;
      V(sem_data);
      p_pos++;
      p_pos%=_cap;
    }
    void Pop(T& out)
    {
      P(sem_data);
      out=v[c_pos];
      V(sem_blank);
      c_pos++;
      c_pos%=_cap;
    }
    ~ring()
    {
      sem_destroy(&sem_data);
      sem_destroy(&sem_blank);
    }
};
void* produce(void* arg)
{
  ring<int>* rq=(ring<int>*) arg;
  while(true)
  {
    sleep(1);
    int a=rand()%100+1;
    rq->Push(a);
    cout<<"produce done:"<<a<<endl;
  }
}
void* consume(void* arg)
{
  ring<int>* rq=(ring<int>*) arg;
  while(true)
  {
    sleep(2);
    int a=0;
    rq->Pop(a);
    cout<<"consume done:"<<a<<endl;
  }
}

int main()
{
  pthread_t p,c;
  ring<int>* rp=new ring<int>();
  srand((unsigned long)time(NULL));
  pthread_create(&p,NULL,produce,rp);
  pthread_create(&c,NULL,consume,rp);
  pthread_join(p,NULL);
  pthread_join(c,NULL);
  return 0;
}
